package com.example.activitiydemo;

import com.alibaba.fastjson.JSONObject;
import com.example.activitiydemo.dao.ActGeBytearrayMapper;
import com.example.activitiydemo.entity.ActGeBytearray;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.deploy.DeploymentManager;
import org.activiti.engine.impl.persistence.deploy.ProcessDefinitionCacheEntry;
import org.activiti.engine.impl.persistence.entity.ByteArrayEntity;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.ObjectUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@SpringBootTest
public class TaskDemo {

	/**
	 * 撤回到上一个节点
	 */
	@Test
	public void demo() {
		String processInstanceId = "25001";
		String nowUserId = "王五";
		//        1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		final TaskService taskService = processEngine.getTaskService();
		final HistoryService historyService = processEngine.getHistoryService();
		final RepositoryService repositoryService = processEngine.getRepositoryService();
		final RuntimeService runtimeService = processEngine.getRuntimeService();
		//获取待执行的任务节点
		Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
		if(task == null){
			// throw new Exception("sorry,the process is not started or has finished, cannot be withdrawn");
			System.out.println("sorry,the process is not started or has finished, cannot be withdrawn");
		}
		//通过processInstanceId查询历史节点
		List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
				.processInstanceId(processInstanceId)
				.orderByTaskCreateTime()
				.asc()
				.list();
		String myTaskId = null;
		HistoricTaskInstance myTask = null;
		//找到当前运行的节点
		HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//		ProcInstance procInstance = procInstanceMapper.selectById(processInstance.getBusinessKey()).get(0);
//		SysUser startUser = sysUserService.selectUserById(procInstance.getUserId());
//		List<SysUser> currUsers = findCurrUsers(task, startUser);
//		System.out.println("----------- =-= -------currUser-----------------------"+currUsers.get(0).getUserId());
//		System.out.println("------ =-= ------nowUserId--------------------------"+nowUserId);
//		for (HistoricTaskInstance hti : htiList) {
//			//判断一下当前的用户是否为当前任务的审批负责人 ， 感觉后面通过权限赋予也可以不加这个判断
//			//if (currUsers.get(0).getUserId().equals(nowUserId)&& hti.getId().equals(task.getId())) {
//			if ( currUsers.get(0).getUserId().toString().equals(nowUserId)&&hti.getId().equals(task.getId())) {
//				myTaskId = hti.getId();  //当前任务id
//				myTask = hti;
//				break;
//			}
//		}
//		if (null == myTaskId) {
//			//throw new Exception("该任务非当前用户提交，无法撤回");
//			System.out.println("该任务非当前用户提交，无法撤回~~!!");
//		}
		//TODO
		for (HistoricTaskInstance hti : htiList) {
			//判断一下当前的用户是否为当前任务的审批负责人 ， 感觉后面通过权限赋予也可以不加这个判断
			//if (currUsers.get(0).getUserId().equals(nowUserId)&& hti.getId().equals(task.getId())) {
			if (Objects.equals(hti.getAssignee(), nowUserId)) {
				myTaskId = hti.getId();  //当前任务id
				myTask = hti;
				break;
			}
		}
		String processDefinitionId = myTask.getProcessDefinitionId();
		//获取流程模型
		BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
		String myActivityId = null;
		//查询已经完成的流程节点，查询到上一条已完成的节点，则跳出循环
		List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
				.executionId(myTask.getExecutionId())
				.finished()
				.orderByHistoricActivityInstanceStartTime()
				.desc()
				.list();
		System.out.println("---------------the latest finished---------------"+haiList.get(0));
		myActivityId = haiList.get(0).getActivityId();
//        for (HistoricActivityInstance hai : haiList) {
//            if (myTaskId.equals(hai.getTaskId())) {
//                myActivityId = hai.getActivityId();
//                break;
//            }
//        }
		//最近一个已完成节点的 FlowNode
		FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);
		//原本的活动方向
		Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
		String activityId = execution.getActivityId();
		FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
		//记录原活动方向
		List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
		oriSequenceFlows.addAll(flowNode.getOutgoingFlows());
		//清理活动方向
		flowNode.getOutgoingFlows().clear();
		//建立新方向
		List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
		SequenceFlow newSequenceFlow = new SequenceFlow();
		newSequenceFlow.setId("newSequenceFlowId"+" WITHDRAW: "+ LocalDateTime.now());
		//新方向的源头---当前节点
		newSequenceFlow.setSourceFlowElement(flowNode);
		//新方向的目标---上一个已完成节点
		newSequenceFlow.setTargetFlowElement(myFlowNode);
		newSequenceFlowList.add(newSequenceFlow);
		flowNode.setOutgoingFlows(newSequenceFlowList);

		Authentication.setAuthenticatedUserId(nowUserId);
		taskService.addComment(task.getId(), task.getProcessInstanceId(), "撤回");
		//完成任务
		taskService.complete(task.getId());
		//恢复原方向
		flowNode.setOutgoingFlows(oriSequenceFlows);
		System.out.println("------------------withdraw successfully！！----------------------------");
//		logger.info("退回成功！");
	}

	/**
	 * 展示历史Activity表
	 */
	@Test
	public void hisActInst(){
		String proInstanceId = "40001";
		String nowUserId = "王五";
		//        1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		final TaskService taskService = processEngine.getTaskService();
		final HistoryService historyService = processEngine.getHistoryService();

		HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(proInstanceId).singleResult();
		String processInstanceId = instance.getId();
//		//获取待执行的任务节点
//		List<Task> task = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
//		if(ObjectUtils.isEmpty(task)){
//			// throw new Exception("sorry,the process is not started or has finished, cannot be withdrawn");
//			System.out.println("sorry,the process is not started or has finished, cannot be withdrawn");
//		}
		//通过processInstanceId查询历史节点
		List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
				.processInstanceId(processInstanceId)
				.orderByTaskCreateTime()
				.asc()
				.list();
//		String myTaskId = null;
		HistoricTaskInstance myTask = null;
		//找到当前运行的节点
		HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//		ProcInstance procInstance = procInstanceMapper.selectById(processInstance.getBusinessKey()).get(0);
//		SysUser startUser = sysUserService.selectUserById(procInstance.getUserId());
//		List<SysUser> currUsers = findCurrUsers(task, startUser);
//		for (HistoricTaskInstance hti : htiList) {
//			//判断一下当前的用户是否为当前任务的审批负责人 ， 感觉后面通过权限赋予也可以不加这个判断
//			//if (currUsers.get(0).getUserId().equals(nowUserId)&& hti.getId().equals(task.getId())) {
//			if ( hti.getId().equals(task.getId())) {
//				myTaskId = hti.getId();  //当前任务id
//				myTask = hti;
//				break;
//			}
//		}
//		if (null == myTaskId) {
//			//throw new Exception("该任务非当前用户提交，无法撤回");
//			System.out.println("该任务非当前用户提交，无法撤回~~!!");
//		}
		//TODO
		for (HistoricTaskInstance hti : htiList) {
			//判断一下当前的用户是否为当前任务的审批负责人 ， 感觉后面通过权限赋予也可以不加这个判断
			//if (currUsers.get(0).getUserId().equals(nowUserId)&& hti.getId().equals(task.getId())) {
			if (Objects.equals(hti.getAssignee(), nowUserId)) {
//				myTaskId = hti.getId();  //当前任务id
				myTask = hti;
				break;
			}
		}
		List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
				.processInstanceId(processInstanceId)
				.finished()
				.orderByHistoricActivityInstanceStartTime()
				.desc()
				.list();
		System.out.println(JSONObject.toJSONString(haiList, true));
//		return haiList;
	}

	/**
	 * 回退到指定节点处 TODO 多人会签节点的退回指定节点
	 * @return
	 */
	@Test
	public void rollBackToSpec() {
		String processInstanceId = "40001";
		String nowUserId = "李四1";
		String tarActivityId = "Task_0wj3769";
		//        1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		final TaskService taskService = processEngine.getTaskService();
		final HistoryService historyService = processEngine.getHistoryService();
		final RepositoryService repositoryService = processEngine.getRepositoryService();
		final RuntimeService runtimeService = processEngine.getRuntimeService();
		//获取待执行的任务节点
		List<Task> task = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
		if(ObjectUtils.isEmpty(task)){
			// throw new Exception("sorry,the process is not started or has finished, cannot be withdrawn");
			System.out.println("sorry,the process is not started or has finished, cannot be withdrawn");
		}
		//通过processInstanceId查询历史节点
		List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
				.processInstanceId(processInstanceId)
				.orderByTaskCreateTime()
				.asc()
				.list();
		String myTaskId = null;
		HistoricTaskInstance myTask = null;
		//找到当前运行的节点
		HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
		String processDefinitionId = processInstance.getProcessDefinitionId();
		//获取流程模型
		BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
		//想要回退到的节点位置
		System.out.println(tarActivityId);
		FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(tarActivityId);
		//原本的活动方向
		Execution execution = runtimeService.createExecutionQuery().executionId(task.get(0).getExecutionId()).singleResult();
		String activityId = execution.getActivityId();
		FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
		//记录原活动方向
		List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
		oriSequenceFlows.addAll(flowNode.getOutgoingFlows());
		//清理活动方向
		flowNode.getOutgoingFlows().clear();
		//建立新方向
		List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
		SequenceFlow newSequenceFlow = new SequenceFlow();
		newSequenceFlow.setId("newSequenceFlowId"+" ROLLBACK: "+ LocalDateTime.now());
		//新方向的源头---当前节点
		newSequenceFlow.setSourceFlowElement(flowNode);
		System.out.println("--------------new flow-----------------"+flowNode);
		//新方向的目标---要回退的节点
		System.out.println("--------------target flow-----------------"+myFlowNode);
		newSequenceFlow.setTargetFlowElement(myFlowNode);
		newSequenceFlowList.add(newSequenceFlow);
		flowNode.setOutgoingFlows(newSequenceFlowList);

		Authentication.setAuthenticatedUserId(nowUserId);
		for (int i = 0; i < task.size(); i++) {
			// TODO 多人会签节点退回 所有节点回退即可
//			taskService.deleteTask(task.get(i).getId(), "回退", Boolean.TRUE);
			taskService.addComment(task.get(i).getId(), task.get(i).getProcessInstanceId(), "回退");
			//完成任务
			System.out.println("========================完成任务====================");
			taskService.complete(task.get(i).getId());
		}

		//恢复原方向
		flowNode.setOutgoingFlows(oriSequenceFlows);
		System.out.println("------------------RollBack successfully！！----------------------------");
		//将退回完成后的当前节点的task返回
//        HistoricActivityInstance historicActivityInstance = historyService.createHistoricActivityInstanceQuery().activityId(tarActivityId).singleResult();
//        return historicActivityInstance.getTaskId();
	}

	/**
	 * 回退到指定节点处 TODO 退回到指定多人会签节点
	 */
	@Test
	public void rollBackToSpec1() {
		String processInstanceId = "40001";
		String nowUserId = "李四1";
		//TODO 退回上一节点为 会签节点时 指向上一节点的网关节点
		String tarActivityId = "Gateway_1bdorji";
		//        1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		final TaskService taskService = processEngine.getTaskService();
		final HistoryService historyService = processEngine.getHistoryService();
		final RepositoryService repositoryService = processEngine.getRepositoryService();
		final RuntimeService runtimeService = processEngine.getRuntimeService();
		//获取待执行的任务节点
		Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
		if(task == null){
			// throw new Exception("sorry,the process is not started or has finished, cannot be withdrawn");
			System.out.println("sorry,the process is not started or has finished, cannot be withdrawn");
		}
		//通过processInstanceId查询历史节点
		List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
				.processInstanceId(processInstanceId)
				.orderByTaskCreateTime()
				.asc()
				.list();
		String myTaskId = null;
		HistoricTaskInstance myTask = null;
		//找到当前运行的节点
		HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
		String processDefinitionId = processInstance.getProcessDefinitionId();
		//获取流程模型
		BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
		//想要回退到的节点位置
		System.out.println(tarActivityId);
		FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(tarActivityId);
		//原本的活动方向
		Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
		String activityId = execution.getActivityId();
		FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
		//记录原活动方向
		List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
		oriSequenceFlows.addAll(flowNode.getOutgoingFlows());
		//清理活动方向
		flowNode.getOutgoingFlows().clear();
		//建立新方向
		List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
		SequenceFlow newSequenceFlow = new SequenceFlow();
		newSequenceFlow.setId("newSequenceFlowId"+" ROLLBACK: "+ LocalDateTime.now());
		//新方向的源头---当前节点
		newSequenceFlow.setSourceFlowElement(flowNode);
		System.out.println("--------------new flow-----------------"+flowNode);
		//新方向的目标---要回退的节点
		System.out.println("--------------target flow-----------------"+myFlowNode);
		newSequenceFlow.setTargetFlowElement(myFlowNode);
		newSequenceFlowList.add(newSequenceFlow);
		flowNode.setOutgoingFlows(newSequenceFlowList);

		Authentication.setAuthenticatedUserId(nowUserId);
		taskService.addComment(task.getId(), task.getProcessInstanceId(), "回退");
		//完成任务
		System.out.println("========================完成任务====================");
		taskService.complete(task.getId());

		//恢复原方向
		flowNode.setOutgoingFlows(oriSequenceFlows);
		System.out.println("------------------RollBack successfully！！----------------------------");
		//将退回完成后的当前节点的task返回
//        HistoricActivityInstance historicActivityInstance = historyService.createHistoricActivityInstanceQuery().activityId(tarActivityId).singleResult();
//
//        return historicActivityInstance.getTaskId();
	}


	@Resource
	ActGeBytearrayMapper actGeBytearrayMapper;


	@Test
	public void demo1() {
		//        1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		final TaskService taskService = processEngine.getTaskService();
		final ManagementService managementService = processEngine.getManagementService();
		final RepositoryService repositoryService = processEngine.getRepositoryService();
		Task userTask = taskService.createTaskQuery()
				.taskId("135005")
//				.taskAssignee(assignee)
				.singleResult();

		final BpmnModel bpmnModel = repositoryService.getBpmnModel(userTask.getProcessDefinitionId());
		final Process process = bpmnModel.getMainProcess();
		process.removeFlowElement("flow4");//移除最终节点连线
		process.addFlowElement(createUserTask("add", "First task", "fred"));//新增节点
		process.addFlowElement(createSequenceFlow("usertask3", "add"));//新增节点 于原节点连线
		process.addFlowElement(createSequenceFlow("add", "endevent1"));//新增节点 于原节点连线
		//重新绘画图形
		new BpmnAutoLayout(bpmnModel).execute();
		BpmnXMLConverter converter = new BpmnXMLConverter();
//把bpmnModel对象转换成字符
		byte[] bytes = converter.convertToXML(bpmnModel);
		//清除缓存
		ProcessEngineConfigurationImpl configuration = (ProcessEngineConfigurationImpl) processEngine.getProcessEngineConfiguration();
		DeploymentManager deploymentManager = configuration.getDeploymentManager();
		deploymentManager.getProcessDefinitionCache().remove(userTask.getProcessDefinitionId());

//		String xmlContenxt = new String(bytes);
		List<ActGeBytearray> actGeBytearrayList = actGeBytearrayMapper.getActGeBytearrayList(userTask.getProcessDefinitionId());
		actGeBytearrayList = actGeBytearrayList.stream().filter(item -> item.getName().endsWith(".bpmn")).peek(item -> {
			item.setBytes(bytes);
		}).collect(Collectors.toList());
		if (ObjectUtils.isNotEmpty(actGeBytearrayList)) actGeBytearrayMapper.updateById(actGeBytearrayList.get(0));
	}

	@Test
	public void demo2() {
//		if (CollectionUtils.isEmpty(dto.getTaskModelList())) {
//			log.error("加签节点没有提供增加节点");
//			return;
//		}
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		ManagementService managementService = processEngine.getManagementService();
		final TaskService taskService = processEngine.getTaskService();
			Task userTask = taskService.createTaskQuery()
				.taskId("135005")
//				.taskAssignee(assignee)
				.singleResult();
		managementService.executeCommand(new GetProcessCmd(userTask.getProcessDefinitionId()));
		//确保这里一定可以从缓存中拿到流程定义相关信息
		ProcessDefinitionCacheEntry processDefinitionCacheEntry = managementService.executeCommand(new GetProcessDefinitionCacheEntryCmd(userTask.getProcessDefinitionId()));
		Process process = processDefinitionCacheEntry.getProcess();
//		List<UserTask> userTasks = new ArrayList<>(/*dto.getTaskModelList().size()*/);

		// 批量生成任务，将用户自定义的相关流程信息转为activity的userTask  TODO 如果添加条件，当条件不满足时，目前只能跳过节点，不能直接结束
//		for (ProcessTask taskModel : dto.getTaskModelList()) {
//			UserTask userTask = GenerateActivityUtils.transformation(taskModel);
//			if (Objects.isNull(userTask)) continue;
//
//			userTasks.add(userTask);
//			process.addFlowElement(userTask);
//		}

//		for (int i = 0; i < userTasks.size(); i++) {
//			Task userTask = taskService.createTaskQuery()
//				.taskId("72506")
//				.taskAssignee(assignee)
//				.singleResult();
//			SequenceFlow sequenceFlow;
//			if (i == userTasks.size() - 1) {
				//是最后一个任务节点
//				String lastNodeId = dto.getTargetNodeId();
//				sequenceFlow = GenerateActivityUtils.createSequenceFlow(userTask.getId() + "---->>>>" + lastNodeId, userTask.getId() + "---->>>>" + lastNodeId,
//						userTask.getId(), lastNodeId, userTask.getSkipExpression());
//				sequenceFlow.setTargetFlowElement(process.getFlowElement(lastNodeId));
//				userTask.setOutgoingFlows(Lists.newArrayList(sequenceFlow));
//			} else {
//				//不是最后一个节点
//				sequenceFlow = GenerateActivityUtils.createSequenceFlow(userTask.getId() + "--->>>" + userTasks.get(i + 1).getId(), userTask.getId() + "--->>>" + userTasks.get(i + 1).getId(), userTask.getId(),
//						userTasks.get(i + 1).getId(), userTask.getSkipExpression());
//				sequenceFlow.setTargetFlowElement(userTasks.get(i + 1));
//				userTask.setOutgoingFlows(Lists.newArrayList(sequenceFlow));
//			}
//			process.addFlowElement(sequenceFlow);
		process.removeFlowElement("flow4");//移除最终节点连线
		process.addFlowElement(createUserTask("add", "First task", "fred"));//新增节点
		process.addFlowElement(createSequenceFlow("usertask3", "add"));//新增节点 于原节点连线
		process.addFlowElement(createSequenceFlow("add", "endevent1"));//新增节点 于原节点连线
//		}
		//更新缓存，确保缓存中存储的是最新的流程数据
		processDefinitionCacheEntry.setProcess(process);

//		new UpdateByteArrayCmd(new ByteArrayEntityImpl(), "");
		//新增节点时，加签第一个节点ID，即将为待办节点
//		String addTodoNodeId = dto.getTaskModelList().get(0).getTaskId();
//		managementService.executeCommand(new JumpNodeCmd(dto.getTaskId(), addTodoNodeId, dto.getVars()));
//		if (dto.isPersistenceDataToDataBase()) {
//			new AddNodeDao().persistenceDataToDataBase(dto.getProcessDefinitionId(), dto.getProcessInstanceId(), dto.getTargetNodeId(), dto.getTaskModelList(), processEngine);
//		}
	}


	@Test
	public void rollBackToSpec2() {
		String processInstanceId = "87501";
		String nowUserId = "王五";
		//TODO 退回上一节点为 会签节点时 指向上一节点的网关节点
//		String tarActivityId = "Gateway_1bdorji";
		String tarActivityId = "add";
		//        1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		final TaskService taskService = processEngine.getTaskService();
		final HistoryService historyService = processEngine.getHistoryService();
		final RepositoryService repositoryService = processEngine.getRepositoryService();
		final RuntimeService runtimeService = processEngine.getRuntimeService();
		//获取待执行的任务节点
		Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
		if(task == null){
			// throw new Exception("sorry,the process is not started or has finished, cannot be withdrawn");
			System.out.println("sorry,the process is not started or has finished, cannot be withdrawn");
		}
		//通过processInstanceId查询历史节点
		List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
				.processInstanceId(processInstanceId)
				.orderByTaskCreateTime()
				.asc()
				.list();
		String myTaskId = null;
		HistoricTaskInstance myTask = null;
		//找到当前运行的节点
		HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
		String processDefinitionId = processInstance.getProcessDefinitionId();
		//获取流程模型
		BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
//		bpmnModel.getMainProcess().removeFlowElement("Flow_0i9kc1u");//移除最终节点连线
		bpmnModel.getMainProcess().addFlowElement(createUserTask("add", "First task", "fred"));//新增节点
//		bpmnModel.getMainProcess().addFlowElement(createSequenceFlow("Task_0ixmhzp", "add"));//新增节点 于原节点连线
//		bpmnModel.getMainProcess().addFlowElement(createSequenceFlow("add", "Event_027przs"));//新增节点 于原节点连线
		//想要回退到的节点位置
		System.out.println(tarActivityId);
		FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(tarActivityId);
		//原本的活动方向
		Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
		String activityId = execution.getActivityId();
		FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
		//记录原活动方向
		List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
		oriSequenceFlows.addAll(flowNode.getOutgoingFlows());
		//清理活动方向
		flowNode.getOutgoingFlows().clear();
		//建立新方向
		List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
		SequenceFlow newSequenceFlow = new SequenceFlow();
		newSequenceFlow.setId("newSequenceFlowId"+" ROLLBACK: "+ LocalDateTime.now());
		//新方向的源头---当前节点
		newSequenceFlow.setSourceFlowElement(flowNode);
		System.out.println("--------------new flow-----------------"+flowNode);
		//新方向的目标---要回退的节点
		System.out.println("--------------target flow-----------------"+myFlowNode);
		newSequenceFlow.setTargetFlowElement(myFlowNode);
		newSequenceFlowList.add(newSequenceFlow);
		flowNode.setOutgoingFlows(newSequenceFlowList);
		//TODO
		//建立新方向
		newSequenceFlowList = new ArrayList<>();
		newSequenceFlow = new SequenceFlow();
		newSequenceFlow.setId("newSequenceFlowId"+" ROLLBACK: "+ LocalDateTime.now());
		//新方向的源头---当前节点
		newSequenceFlow.setSourceFlowElement(myFlowNode);
		System.out.println("--------------new flow-----------------"+myFlowNode);
		//新方向的目标---要回退的节点
		final SequenceFlow endFlowNode = oriSequenceFlows.get(0);
		System.out.println("--------------target flow-----------------"+endFlowNode);
		newSequenceFlow.setTargetFlowElement(endFlowNode);
		newSequenceFlowList.add(newSequenceFlow);
		flowNode.setOutgoingFlows(newSequenceFlowList);

		Authentication.setAuthenticatedUserId(nowUserId);
		taskService.addComment(task.getId(), task.getProcessInstanceId(), "回退");
		//完成任务
		System.out.println("========================完成任务====================");
		taskService.complete(task.getId());

		//恢复原方向
//		flowNode.setOutgoingFlows(oriSequenceFlows);
		System.out.println("------------------RollBack successfully！！----------------------------");
	}

//	public static void main(String[] args) throws IOException, XMLStreamException {
//		InputStream inputStream = new FileInputStream(
//
//				"C:\\Users\\wangshuai9776\\IdeaProjects\\job\\job1\\test\\activitiyDemo\\src\\main\\resources\\bpmn\\diagram.bpmn");
//
//		BpmnXMLConverter converter = new BpmnXMLConverter();
//
//		XMLInputFactory factory = XMLInputFactory.newInstance();
//
//		BpmnModel bpmnModel = converter.convertToBpmnModel(factory.createXMLStreamReader(inputStream));
//
//		Process process = bpmnModel.getMainProcess();
//		process.removeFlowElement("flow4");//移除最终节点连线
//		process.addFlowElement(createUserTask("add", "First task", "fred"));//新增节点
//		process.addFlowElement(createSequenceFlow("usertask3", "add"));//新增节点 于原节点连线
//		process.addFlowElement(createSequenceFlow("add", "endevent1"));//新增节点 于原节点连线
//
////		ServiceTask hookTask = new ServiceTask();
////
////		hookTask.setName("拦截");
////
////		hookTask.setId("hook");
////
////		process.addFlowElement(hookTask);
////
////
////		process.findFlowElementsOfType(UserTask.class).forEach(task -> {
////				task.getOutgoingFlows().forEach(flow -> {
////						SequenceFlow toHook = new SequenceFlow();
////						toHook.setSourceRef(task.getId());
////						toHook.setTargetRef("hook");
////						process.addFlowElement(toHook);
////						SequenceFlow fromHook = new SequenceFlow();
////						fromHook.setSourceRef("hook");
////						fromHook.setTargetRef(flow.getTargetRef());
////						process.addFlowElement(fromHook);
////						process.removeFlowElement(flow.getId());
////					});
////				});
//
//		// 这行代码是重新布局
//		new BpmnAutoLayout(bpmnModel).execute();
//		Files.write(Paths.get("C:\\Users\\wangshuai9776\\IdeaProjects\\job\\job1\\test\\activitiyDemo\\src\\main\\resources\\bpmn\\diagram.bpmn"),
//		converter.convertToXML(bpmnModel));
//	}

	protected static UserTask createUserTask(String id, String name, String assignee) {
		UserTask userTask = new UserTask();
		userTask.setName(name);
		userTask.setId(id);
		userTask.setAssignee(assignee);
		return userTask;
	}

	protected static SequenceFlow createSequenceFlow(String from, String to) {
		SequenceFlow flow = new SequenceFlow();
		flow.setSourceRef(from);
		flow.setTargetRef(to);
		return flow;
	}

	class GetProcessDefinitionCacheEntryCmd implements Command<ProcessDefinitionCacheEntry> {
		String processDefinitionId;

		public GetProcessDefinitionCacheEntryCmd(String processDefinitionId) {
			this.processDefinitionId = processDefinitionId;
		}

		@Override
		public ProcessDefinitionCacheEntry execute(CommandContext commandContext) {
			DeploymentManager deploymentManager = commandContext.getProcessEngineConfiguration().getDeploymentManager();
			ProcessDefinitionCacheEntry processDefinitionCacheEntry = deploymentManager.getProcessDefinitionCache().get(processDefinitionId);
			return processDefinitionCacheEntry;
		}

	}
	class GetProcessCmd implements Command<Process> {

		private String processDefinitionId;

		public GetProcessCmd(String processDefinitionId) {
			this.processDefinitionId = processDefinitionId;
		}

		@Override
		public Process execute(CommandContext commandContext) {
			BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionId);
			if (CollectionUtils.isEmpty(bpmnModel.getProcesses())) {
//				log.error("未找不到任何流程");
				return new Process();
			}


			return bpmnModel.getProcesses().get(0);
		}
	}

	class UpdateByteArrayCmd implements Command<Object> {
		/**
		 * act_ge_bytearray表实体类
		 */
		private ByteArrayEntity byteArrayEntity;
		/**
		 * procDefId 流程定义id
		 */
		private String procDefId;

		public UpdateByteArrayCmd(ByteArrayEntity byteArrayEntity, String procDefId) {
			this.byteArrayEntity = byteArrayEntity;
			this.procDefId = procDefId;
		}


		@Override
		public Object execute(CommandContext commandContext) {
			try {
				final ProcessDefinition processDefinition = commandContext.getDbSqlSession().createProcessDefinitionQuery().processDefinitionId(procDefId).singleResult();
				byteArrayEntity.setDeploymentId(processDefinition.getDeploymentId());
				//org.activiti.engine.ActivitiOptimisticLockingException: ByteArrayEntity[id=2, name=null, size=4479] was updated by another transaction concurrently
				//更新act_ge_bytearray表，使用了乐观锁，必须加上版本号
				commandContext.getDbSqlSession().update(this.byteArrayEntity);
				//清除缓存
				commandContext.getProcessEngineConfiguration().getProcessDefinitionCache().remove(procDefId);
				System.out.println(String.format("-------------更新流程定义并删除缓存deployId:%s, ，procDefId:%s--------------", this.byteArrayEntity.getDeploymentId(), procDefId));
			} catch (Exception e) {
				throw new RuntimeException("更新流程定义文件异常", e);
			}

			return null;
		}
	}
}
